package com.whj.apipassenger.service.impl;

import com.alibaba.nacos.api.utils.StringUtils;
import com.whj.apipassenger.remote.ServicePassengerUserClient;
import com.whj.apipassenger.remote.ServiceVerificationClient;
import com.whj.apipassenger.service.VerificationCodeService;
import com.whj.internalcommon.constant.CommonStatusEnum;
import com.whj.internalcommon.constant.IdentityConstant;
import com.whj.internalcommon.constant.TokenTypeConstants;
import com.whj.internalcommon.dto.ResponseResult;
import com.whj.internalcommon.request.VerificationCodeDTO;
import com.whj.internalcommon.response.NumberCodeResponse;
import com.whj.internalcommon.response.TokenResponse;
import com.whj.internalcommon.utils.JwtUtils;
import com.whj.internalcommon.utils.RedisTokenKeyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @Auther: wanghaijun
 * @Date: 2022/12/25 - 12 - 25 - 16:56 
 * @Description: com.whj.apipassenger.service.impl
 */

@Service
public class VerificationCodeServiceImpl implements VerificationCodeService {


    @Autowired
    private ServiceVerificationClient serviceVerificationClient;

    @Autowired
    private ServicePassengerUserClient servicePassengerUserClient;


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 接收验证码服务，获取验证码，并传到redis中
     *
     * @param passengerPhone 手机号
     * @return
     */
    @Override
    public ResponseResult generatorCode(String passengerPhone) {
        //调用验证码服务，获取验证码
        ResponseResult<NumberCodeResponse> numberCodeResponse = serviceVerificationClient.getNumberCode(6);
        int numberCode = numberCodeResponse.getData().getNumberCode();

        //存入redis
        //key value ttl
        //前缀加手机号 注：当有拷贝的欲望时可以考虑是否抽象为方法
        //String key =verificationCodePrefix+passengerPhone;
        String key = RedisTokenKeyUtils.keyByPhone(passengerPhone, IdentityConstant.PASSENGER_IDENTITY);
        //ttl 等于2分钟
        stringRedisTemplate.opsForValue().set(key, numberCode + "", 2, TimeUnit.MINUTES);
        //通过短信服务商将对应的验证码发送到手机上，阿里短信服务，腾讯短信通，华信，容联

        // 返回值
        return ResponseResult.success();
    }


    /**
     * 验证乘客发送的验证码，并判断用户是否存在，存在返回token，不存在，注册并返回token
     *
     * @param passengerPhone   手机号
     * @param verificationCode 验证码
     * @return
     */
    @Override
    public ResponseResult checkCode(String passengerPhone, String verificationCode) {
        //根据手机号，去redis读取验证码

        //生成key       注：当有拷贝的欲望时可以考虑是否抽象为方法
        //String key =verificationCodePrefix+passengerPhone;
        String key = RedisTokenKeyUtils.keyByPhone(passengerPhone, IdentityConstant.PASSENGER_IDENTITY);

        //根据key 获取value
        String redisKey = stringRedisTemplate.opsForValue().get(key);

        //校验验证码
        //验证码过期
        if (StringUtils.isBlank(redisKey)) {
            return ResponseResult.fail(CommonStatusEnum.VERIFICATION_CODE_OVERDUE.getCode(), CommonStatusEnum.VERIFICATION_CODE_OVERDUE.getValue());
        }
        //验证码错误
        if (!verificationCode.trim().equals(redisKey.trim())) {
            return ResponseResult.fail(CommonStatusEnum.VERIFICATION_CODE_ERROR.getCode(), CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }

        //判断是否有用户，并处理
        VerificationCodeDTO verificationCodeDTO = new VerificationCodeDTO();
        verificationCodeDTO.setPassengerPhone(passengerPhone);

        //调用service-passenger-user服务
        servicePassengerUserClient.loginOrRegister(verificationCodeDTO);

        //颁发令牌
        String accessToken = JwtUtils.generatorToken(passengerPhone, IdentityConstant.PASSENGER_IDENTITY, TokenTypeConstants.ACCESS_TOKEN_TYPE);
        String refreshToken = JwtUtils.generatorToken(passengerPhone, IdentityConstant.PASSENGER_IDENTITY, TokenTypeConstants.REFRESH_TOKEN_TYPE);

        //将token保存到redis中
        String accessTokenKey = RedisTokenKeyUtils.keyByTokenMsg(passengerPhone, IdentityConstant.PASSENGER_IDENTITY, TokenTypeConstants.ACCESS_TOKEN_TYPE);
        stringRedisTemplate.opsForValue().set(accessTokenKey, accessToken, 30, TimeUnit.DAYS);
        //refreshToken比accessToken晚过期一天，保证accessToken过期后refreshToken有效
        String refreshTokenKey = RedisTokenKeyUtils.keyByTokenMsg(passengerPhone, IdentityConstant.PASSENGER_IDENTITY, TokenTypeConstants.REFRESH_TOKEN_TYPE);
        stringRedisTemplate.opsForValue().set(refreshTokenKey, refreshToken, 31, TimeUnit.DAYS);

        //响应
        TokenResponse tokenResponse = new TokenResponse();
        tokenResponse.setAccessToken(accessToken);
        tokenResponse.setRefreshToken(refreshToken);

        return ResponseResult.success(tokenResponse);
    }
}
